<?php
/**
 * fast RPC sdk
 *
 * remote process use fast-cgi protocal
 * @author <lowellzhong@gmail.com>
 *
 * code example:
 *
 * $rpc = new FastRPC;
 * $rpc->setTimeout(0.1, 0.01);			//set call timeout and socket read/write timeout
 * $rpc->setServer('10.134.11.13', '8080');	//set RPC server address
 * $photos = $rpc->call("photo.list", array('userid' => 123456, 'page' => 4, 'pagesize' => 30));
 * ...
 *
 */

if (file_exists('/opt/wwwroot/i.sdo.com/sdk/uc/libraries/UCLibTcpSocket.php')) {
	require_once('/opt/wwwroot/i.sdo.com/sdk/uc/libraries/UCLibTcpSocket.php');
} else {
	require_once(dirname(__FILE__).'/UCLibTcpSocket.php');
}

class ApiPoolClientShort
{
	private $host = "127.0.0.1";
	private $port = 9000;
	private $_callTimeout = 0.1;	//second
	private $_connTimeout = 0.01;	//usecond
    private $_error;

	function __construct($host = null, $port = null) {
		if(!is_null($host) && !is_null($port))
			$this->setServer($host, $port);
	}
    
    public function getLastError() {
        return $this->_error;
    }

	function setServer($host, $port) {
		$this->host = $host;
		$this->port = $port;
	}

	function setTimeout($conn_timeout = 0.01, $call_timeout = 0.1) {
		if($call_timeout < $conn_timeout) {
			$call_timeout = $conn_timeout;
		}
        $this->_connTimeout = $conn_timeout;
		$this->_callTimeout = $call_timeout;   
	}
	
	function send($packet) {
		$sock = new UCLibTcpSocket();
        $timeout = new UCLibTimeout($this->_callTimeout);
        $conn_ret = $sock->connect($this->host, $this->port, $this->_connTimeout);
        if(false === $conn_ret){
            $this->_error = 'connect timeout#'.$sock->getLastErrorMsg();
            $sock->close();
            return false;
        }

        $len = $sock->write($packet, strlen($packet), $timeout);
        if(false === $len) {
            $this->_error = 'write timeout#'.$sock->getLastErrorMsg();
			$sock->close();
            return false;
       	}

       	return true;
	}
    
	function sendReceive($packet) {     
		$sock = new UCLibTcpSocket();
        $timeout = new UCLibTimeout($this->_callTimeout);
        $conn_ret = $sock->connect($this->host, $this->port, $this->_connTimeout);
        if(false === $conn_ret){
            $this->_error = 'connect timeout#'.$sock->getLastErrorMsg();
            $sock->close();
            return false;
        }

        $len = $sock->write($packet, strlen($packet), $timeout);
        if(false === $len) {
            $this->_error = 'write timeout#'.$sock->getLastErrorMsg();
			$sock->close();
            return false;
       	}

       	$tmp_header  = $sock->read(6,$timeout);
		if($tmp_header === false){
 	 		$this->_error = 'read header timeout 0#'.$sock->getLastErrorMsg();
     		$sock->close();
      		return false;
		}
		
		if ($sock->getLastError() != 0) {
			$this->_error = 'read header timeout 1#'.$sock->getLastErrorMsg();
			$sock->close();
			return false;
		}
		
		$len = intval($tmp_header,16); 
       	$tmp = $sock->read($len,$timeout);
       	if($tmp === false){
       	 	$this->_error = 'read content timeout 0#'.$sock->getLastErrorMsg();
           	$sock->close();
            return false;
       	}
       	
		if ($sock->getLastError() != 0) {
			$this->_error = 'read content timeout 1#'.$this->sock->getLastErrorMsg();
			$sock->close();
			return false;
		}
		
       	return $tmp_header.$tmp;
	}
}

class ApiPoolClientLong
{
	private $sock = null;
	private $host = "127.0.0.1";
	private $port = 9000;
	private $_callTimeout = 0.1;	//second
	private $_connTimeout = 0.01;	//usecond
    private $_error;

	function __construct($host = null, $port = null) {
		if(!is_null($host) && !is_null($port))
			$this->setServer($host, $port);
	}
    
    public function getLastError() {
        return $this->_error;
    }

	function setServer($host, $port) {
		$this->host = $host;
		$this->port = $port;
		$this->maintainConnection();
	}

	function setTimeout($conn_timeout = 0.01, $call_timeout = 0.1) {
		if($call_timeout < $conn_timeout) {
			$call_timeout = $conn_timeout;
		}
        $this->_connTimeout = $conn_timeout;
		$this->_callTimeout = $call_timeout;
	}
	
	private function maintainConnection() {
		if ($this->sock != null) {
			$this->sock->clearError();
			return true;
		}

		$this->sock = new UCLibTcpSocket();
		$con = $this->sock->connect($this->host, $this->port, $this->_connTimeout);
		if ($con === false) {
            $this->_error = 'connect timeout#'.$this->sock->getLastErrorMsg();
            $this->sock->close();
            $this->sock = null;
            return false;
		}
		
		return true;
	}
    
	function send($packet) {
		if (false === $this->maintainConnection())
			return false;
		
        $timeout = new UCLibTimeout($this->_callTimeout);
		$len = $this->sock->write($packet, strlen($packet), $timeout);
        if(false === $len) {
			$this->_error = 'write timeout#'.$this->sock->getLastErrorMsg();
			$this->sock->close();
			$this->sock = null;
            return false;
		}
		
		return true;
	}
    
	function sendReceive($packet) {
		if (false === $this->maintainConnection())
			return false;
		
        $timeout = new UCLibTimeout($this->_callTimeout);
		$len = $this->sock->write($packet, strlen($packet), $timeout);
        if(false === $len) {
			$this->_error = 'write timeout#'.$this->sock->getLastErrorMsg();
			$this->sock->close();
			$this->sock = null;
            return false;
		}
       	
       	$tmp_header = $this->sock->read(6, $timeout);
		if($tmp_header === false){
 	 		$this->_error = 'read header timeout 0#'.$this->sock->getLastErrorMsg();
     		$this->sock->close();
			$this->sock = null;
     		return false;
		}
		
		if ($this->sock->getLastError() != 0) {
			$this->_error = 'read header timeout 1#'.$this->sock->getLastErrorMsg();
			$this->sock->close();
			$this->sock = null;
			return false;
		}
		
		$len = intval($tmp_header, 16);
       	$tmp = $this->sock->read($len, $timeout);
       	if($tmp === false){
       	 	$this->_error = 'read content timeout 0#'.$this->sock->getLastErrorMsg();
           	$this->sock->close();
			$this->sock = null;
           	return false;
       	}
       	
		if ($this->sock->getLastError() != 0) {
			$this->_error = 'read content timeout 1#'.$this->sock->getLastErrorMsg();
			$this->sock->close();
			$this->sock = null;
			return false;
		}
		
       	return $tmp_header.$tmp;
	}

}

?>
